home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 August (Alt) / CHIP 2005-08.1.iso / program / guvenlik / syslinux-3.07.exe / memdisk / unzip.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-12-07  |  9.9 KB  |  391 lines

  1. /*
  2.  * unzip.c
  3.  * 
  4.  * This is a collection of several routines from gzip-1.0.3 
  5.  * adapted for Linux.
  6.  *
  7.  * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
  8.  * puts by Nick Holloway 1993, better puts by Martin Mares 1995
  9.  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  10.  *
  11.  * Adapted for MEMDISK by H. Peter Anvin, April 2003
  12.  */
  13.  
  14. #include <stdint.h>
  15. #include "memdisk.h"
  16. #include "conio.h"
  17.  
  18. /*
  19.  * gzip declarations
  20.  */
  21.  
  22. #define OF(args)  args
  23. #define STATIC static
  24.  
  25. #define memzero(s, n)     memset ((s), 0, (n))
  26.  
  27. typedef uint8_t  uch;
  28. typedef uint16_t ush;
  29. typedef uint32_t ulg;
  30.  
  31. #define WSIZE 0x8000            /* Window size must be at least 32k, */
  32.                 /* and a power of two */
  33.  
  34. static uch *inbuf;        /* input pointer */
  35. static uch window[WSIZE];    /* sliding output window buffer */
  36.  
  37. static unsigned insize;        /* total input bytes read */
  38. static unsigned inbytes;    /* valid bytes in inbuf */
  39. static unsigned outcnt;        /* bytes in output buffer */
  40.  
  41. /* gzip flag byte */
  42. #define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
  43. #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
  44. #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
  45. #define ORIG_NAME    0x08 /* bit 3 set: original file name present */
  46. #define COMMENT      0x10 /* bit 4 set: file comment present */
  47. #define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
  48. #define RESERVED     0xC0 /* bit 6,7:   reserved */
  49.  
  50. /* Diagnostic functions */
  51. #ifdef DEBUG
  52. #  define Assert(cond,msg) {if(!(cond)) error(msg);}
  53. #  define Trace(x) fprintf x
  54. #  define Tracev(x) {if (verbose) fprintf x ;}
  55. #  define Tracevv(x) {if (verbose>1) fprintf x ;}
  56. #  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
  57. #  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
  58. #else
  59. #  define Assert(cond,msg)
  60. #  define Trace(x)
  61. #  define Tracev(x)
  62. #  define Tracevv(x)
  63. #  define Tracec(c,x)
  64. #  define Tracecv(c,x)
  65. #endif
  66.  
  67. static int  fill_inbuf(void);
  68. static void flush_window(void);
  69. static void error(char *m);
  70. static void gzip_mark(void **);
  71. static void gzip_release(void **);
  72.  
  73. extern ulg crc_32_tab[256];
  74.  
  75. /* Get byte from input buffer */
  76. static inline uch get_byte(void)
  77. {
  78.   if ( inbytes ) {
  79.     uch b = *inbuf++;
  80.     inbytes--;
  81.     return b;
  82.   } else {
  83.     return fill_inbuf();    /* Input buffer underrun */
  84.   }
  85. }
  86.  
  87. /* Unget byte from input buffer */
  88. static inline void unget_byte(void)
  89. {
  90.   inbytes++;
  91.   inbuf--;
  92. }
  93.  
  94. static ulg bytes_out = 0;    /* Number of bytes output */
  95. static uch *output_data;    /* Output data pointer */
  96. static ulg output_size;        /* Number of output bytes expected */
  97.  
  98. static void *malloc(int size);
  99. static void free(void *where);
  100.  
  101. static ulg free_mem_ptr, free_mem_end_ptr;
  102.  
  103. #include "inflate.c"
  104.  
  105. static void *malloc(int size)
  106. {
  107.   void *p;
  108.   
  109.   if (size < 0) error("malloc error");
  110.   
  111.   free_mem_ptr = (free_mem_ptr + 3) & ~3;    /* Align */
  112.   
  113.   p = (void *)free_mem_ptr;
  114.   free_mem_ptr += size;
  115.   
  116.   if (free_mem_ptr >= free_mem_end_ptr)
  117.     error("out of memory");
  118.   
  119.   return p;
  120. }
  121.  
  122. static void free(void *where)
  123. {
  124.   /* Don't care */
  125.   (void)where;
  126. }
  127.  
  128. static void gzip_mark(void **ptr)
  129. {
  130.   *ptr = (void *) free_mem_ptr;
  131. }
  132.  
  133. static void gzip_release(void **ptr)
  134. {
  135.   free_mem_ptr = (long) *ptr;
  136. }
  137.  
  138. /* ===========================================================================
  139.  * Fill the input buffer. This is called only when the buffer is empty
  140.  * and at least one byte is really needed.
  141.  */
  142. static int fill_inbuf(void)
  143. {
  144.   /* This should never happen.  We have already pointed the algorithm
  145.      to all the data we have. */
  146.   printf("failed\nDecompression error: ran out of input data\n");
  147.   die();
  148. }
  149.  
  150. /* ===========================================================================
  151.  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
  152.  * (Used for the decompressed data only.)
  153.  */
  154. static void flush_window(void)
  155. {
  156.     ulg c = crc;         /* temporary variable */
  157.     unsigned n;
  158.     uch *in, *out, ch;
  159.  
  160.     if ( bytes_out+outcnt > output_size )
  161.       error("output buffer overrun");
  162.     
  163.     in = window;
  164.     out = output_data;
  165.     for (n = 0; n < outcnt; n++) {
  166.         ch = *out++ = *in++;
  167.         c = crc_32_tab[(c ^ ch) & 0xff] ^ (c >> 8);
  168.     }
  169.     crc = c;
  170.     output_data = out;
  171.     bytes_out += (ulg)outcnt;
  172.     outcnt = 0;
  173. }
  174.  
  175. static void error(char *x)
  176. {
  177.   printf("failed\nDecompression error: %s\n", x);
  178.   die();
  179. }
  180.  
  181. /* GZIP header */
  182. struct gzip_header {
  183.   uint16_t magic;
  184.   uint8_t method;
  185.   uint8_t flags;
  186.   uint32_t timestamp;
  187.   uint8_t extra_flags;
  188.   uint8_t os_type;
  189. } __attribute__ ((packed));
  190. /* (followed by optional and variable length "extra", "original name",
  191.    and "comment" fields) */
  192.  
  193. struct gzip_trailer {
  194.   uint32_t crc;
  195.   uint32_t dbytes;
  196. } __attribute__ ((packed));
  197.  
  198. /* PKZIP header.  See
  199.  * <http://www.pkware.com/products/enterprise/white_papers/appnote.html>.
  200.  */
  201. struct pkzip_header {
  202.   uint32_t magic;
  203.   uint16_t version;
  204.   uint16_t flags;
  205.   uint16_t method;
  206.   uint16_t modified_time;
  207.   uint16_t modified_date;
  208.   uint32_t crc;
  209.   uint32_t zbytes;
  210.   uint32_t dbytes;
  211.   uint16_t filename_len;
  212.   uint16_t extra_len;
  213. } __attribute__ ((packed));
  214. /* (followed by optional and variable length "filename" and "extra"
  215.    fields) */
  216.  
  217. /* gzip flag byte */
  218. #define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
  219. #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
  220. #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
  221. #define ORIG_NAME    0x08 /* bit 3 set: original file name present */
  222. #define COMMENT      0x10 /* bit 4 set: file comment present */
  223. #define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
  224. #define RESERVED     0xC0 /* bit 6,7:   reserved */
  225.  
  226. /* pkzip flag byte */
  227. #define PK_ENCRYPTED     0x01  /* bit 0 set: file is encrypted */
  228. #define PK_DATADESC       0x08  /* bit 3 set: file has trailing "data
  229.                                    descriptor" */
  230. #define PK_UNSUPPORTED    0xFFF0 /* All other bits must be zero */
  231.  
  232.  
  233. /* Return 0 if (indata, size) points to a ZIP file, and fill in
  234.    compressed data size, uncompressed data size, CRC, and offset of
  235.    data.
  236.  
  237.    If indata is not a ZIP file, return -1. */
  238. int check_zip(void *indata, uint32_t size, uint32_t *zbytes_p,
  239.               uint32_t *dbytes_p, uint32_t *orig_crc, uint32_t *offset_p) {
  240.   struct gzip_header *gzh = (struct gzip_header *)indata;
  241.   struct pkzip_header *pkzh = (struct pkzip_header *)indata;
  242.   uint32_t offset;
  243.  
  244.   if (gzh->magic == 0x8b1f) {
  245.     struct gzip_trailer *gzt = indata + size - sizeof (struct gzip_trailer);
  246.     /* We only support method #8, DEFLATED */
  247.     if (gzh->method != 8)  {
  248.       error("gzip file uses invalid method");
  249.       return -1;
  250.     }
  251.     if (gzh->flags & ENCRYPTED) {
  252.       error("gzip file is encrypted; not supported");
  253.       return -1;
  254.     }
  255.     if (gzh->flags & CONTINUATION) {
  256.       error("gzip file is a continuation file; not supported");
  257.       return -1;
  258.     }
  259.     if (gzh->flags & RESERVED) {
  260.       error("gzip file has unsupported flags");
  261.       return -1;
  262.     }
  263.     offset = sizeof (*gzh);
  264.     if (gzh->flags & EXTRA_FIELD) {
  265.       /* Skip extra field */
  266.       unsigned len = *(unsigned *)(indata + offset);
  267.       offset += 2 + len;
  268.     }
  269.     if (gzh->flags & ORIG_NAME) {
  270.       /* Discard the old name */
  271.       uint8_t *p = indata;
  272.       while (p[offset] != 0 && offset < size) {
  273.         offset++;
  274.       }
  275.       offset++;
  276.     }
  277.     
  278.     if (gzh->flags & COMMENT) {
  279.       /* Discard the comment */
  280.       uint8_t *p = indata;
  281.       while (p[offset] != 0 && offset < size) {
  282.         offset++;
  283.       }
  284.       offset++;
  285.     }
  286.  
  287.     if (offset > size) {
  288.       error ("gzip file corrupt");
  289.       return -1;
  290.     }
  291.     *zbytes_p = size - offset - sizeof (struct gzip_trailer);
  292.     *dbytes_p = gzt->dbytes;
  293.     *orig_crc = gzt->crc;
  294.     *offset_p = offset;
  295.     return 0;
  296.   }
  297.   else if (pkzh->magic == 0x04034b50UL) {
  298.     /* Magic number matches pkzip file. */
  299.     
  300.     offset = sizeof (*pkzh);
  301.     if (pkzh->flags & PK_ENCRYPTED) {
  302.       error("pkzip file is encrypted; not supported");
  303.       return -1;
  304.     }
  305.     if (pkzh->flags & PK_DATADESC) {
  306.       error("pkzip file uses data_descriptor field; not supported");
  307.       return -1;
  308.     }
  309.     if (pkzh->flags & PK_UNSUPPORTED) {
  310.       error("pkzip file has unsupported flags");
  311.       return -1;
  312.     }
  313.  
  314.     /* We only support method #8, DEFLATED */
  315.     if (pkzh->method != 8) {
  316.       error("pkzip file uses invalid method");
  317.       return -1;
  318.     }
  319.     /* skip header */
  320.     offset = sizeof (*pkzh);
  321.     /* skip filename */
  322.     offset += pkzh->filename_len;
  323.     /* skip extra field */
  324.     offset += pkzh->extra_len;
  325.  
  326.     if (offset + pkzh->zbytes > size) {
  327.       error ("pkzip file corrupt");
  328.       return -1;
  329.     }
  330.  
  331.     *zbytes_p = pkzh->zbytes;
  332.     *dbytes_p = pkzh->dbytes;
  333.     *orig_crc = pkzh->crc;
  334.     *offset_p = offset;
  335.     return 0;
  336.   }
  337.   else {
  338.     /* Magic number does not match. */
  339.     return -1;
  340.   }
  341.  
  342.   error ("Internal error in check_zip");
  343.   return -1;
  344. }
  345.  
  346. /*
  347.  * Decompress the image, trying to flush the end of it as close
  348.  * to end_mem as possible.  Return a pointer to the data block,
  349.  * and change datalen.
  350.  */
  351. extern void _end;
  352.  
  353. void *unzip(void *indata, uint32_t zbytes, uint32_t dbytes,
  354.             uint32_t orig_crc, void *target)
  355. {
  356.   /* Set up the heap; it's the 64K after the bounce buffer */
  357.   free_mem_ptr = (ulg)sys_bounce + 0x10000;
  358.   free_mem_end_ptr = free_mem_ptr + 0x10000;
  359.  
  360.   /* Set up input buffer */
  361.   inbuf  = indata;
  362.   /* Sometimes inflate() looks beyond the end of the compressed data,
  363.      but it always backs up before it is done.  So we give it 4 bytes
  364.      of slack. */
  365.   insize = inbytes = zbytes + 4;
  366.  
  367.   /* Set up output buffer */
  368.   outcnt = 0;
  369.   output_data = target;
  370.   output_size = dbytes;
  371.   bytes_out = 0;
  372.  
  373.   makecrc();
  374.   gunzip();
  375.  
  376.   /* Verify that gunzip() consumed the entire input. */
  377.   if (inbytes != 4)
  378.     error("compressed data length error");
  379.  
  380.   /* Check the uncompressed data length and CRC. */
  381.   if ( bytes_out != dbytes )
  382.     error("uncompressed data length error");
  383.  
  384.   if (orig_crc != CRC_VALUE)
  385.     error("crc error");
  386.  
  387.   puts("ok\n");
  388.  
  389.   return target;
  390. }
  391.